package com.gem.day12;

import java.util.*;

/**
 * 本类用来演示Java集合框架之Set接口的实现类:
 * HashSet,它的特点是无序不可重复
 * 
 * 
 * 底层原理:
 * JDK8.0之前				数组+链表
 * JDK8.0及其以后		数组+链表+红黑树
 * 
 * @author easonsy
 * 2020年8月3日 上午9:03:01
 */
public class HashSetDemo {
	public static void main(String[] args) {
		//创建HashSet集合对象
		//默认初始容量（16）
		//默认加载因子 (0.75),即当数组元素到达0.75*16=12时,自动扩容2倍
		Set<Integer> set = new HashSet<>();
		set.add(5);
		set.add(2);
		set.add(3);
		set.add(1);
		set.add(2);

		//遍历集合
		//1.直接打印
		System.out.println(set);

		//2.普通for循环(无法使用)

		//3.增强for循环(支持无序)
		for (Integer i : set) {
			System.out.println(i);
		}

		//4.forEach
		set.forEach(System.out::println);

		//5.迭代器
		Iterator<Integer> iter = set.iterator();
		while (iter.hasNext()) {
			System.out.println(iter.next());
		}

		System.out.println("---------------------------------");

		/*
		 * 当第一个元素添加到Set集合中时,会优先调用这个对象的hashCode()方法得到哈希值,
		 * 根据这个哈希值来决定该对象存放在集合的哪个位置
		 * 当第二个元素添加到Set集合中时,会继续调用这个对象的hashCode()方法得到哈希值,
		 * 此时会有两种情况:
		 * a.哈希值不同,说明是不同的对象,则根据这个哈希值来决定新元素存放的位置
		 * b.哈希值相同,此时还不能说明是相同的对象,所以会继续调用equals()方法,
		 * 如果equals()方法返回true,说明是相同对象,则该元素将不被添加到集合中
		 * 如果equals()方法返回false,说明这两个对象虽然哈希值一样,但是是不同的对象, 
		 * 则在该哈希值对应的位置产生链表
		 * JDK8.0之前,只要产生碰撞,即在链表上加一个元素,随着元素增多,HashSet的性能越低
		 * JDK8.0之后,当碰撞阔值达到8时,自动把链表转换成红黑树,目的是为了提高HashSet的性能
		 */
		Set<User> users = new HashSet<>();
		User u1 = new User("admin", "123");
		User u2 = new User("jack", "123456");
		User u3 = new User("admin", "123");
		users.add(u1);
		users.add(u2);
		users.add(u3);
		users.forEach(System.out::println);
	}
}
